<?php
/*******************************************************************************
Rd/Request/Status.php
Implements Reserve Request model and utilities for RD

Created by Troy Hurteau, NCSU Libraries, NC State University (libraries.opensource@ncsu.edu).

This file is part of NCSU's distribution of ReservesDirect. This version has not been downloaded from Emory University
or the original developers of ReservesDirect. Neither Emory University nor the original developers of ReservesDirect have authorized
or otherwise endorsed or approved this distribution of the software.

Copyright (c) 2004-2006 Emory University, Atlanta, Georgia.

Licensed under the NCSU ReservesDirect License, Version 2.0 (the "License"); 
you may not use this file except in compliance with the License. You may obtain a copy of the full License at
 http://www.lib.ncsu.edu/it/opensource/

ReservesDirect is distributed in the hope that it will be useful,
but is distributed "AS IS" and WITHOUT ANY WARRANTY, without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE, and without any warranty as to non-infringement of any third
party's rights. See the License for the specific language governing permissions and limitations under the License.

The original version of ReservesDirect is located at:
http://www.reservesdirect.org/

This version of ReservesDirect, distributed by NCSU, is located at:
http://code.google.com/p/reservesdirect-ncsu/

*******************************************************************************/

require_once(APPLICATION_PATH . '/lib/Rd/Dao/Reserve/Status.php');

/**
 * 
 * Request Status model and utility object.
 * @author jthurtea
 *
 */

class Rd_Request_Status{
	
	protected static $_activeId = NULL;
	protected static $_inactiveId = NULL;
	protected static $_newId = NULL;
	protected static $_deniedId = NULL;
	protected static $_initialStatus = NULL;
	
	protected $_id = NULL;
	protected $_token = '';
	protected $_staffLabel = '';
	protected $_facultyLabel = '';
	protected $_description = '';
	protected $_enabled = FALSE;
	protected $_order = 0;
	protected $_count = NULL; //lazy loading
	
	public function __construct($statusId)
	{
		$this->load($statusId);
	}
	
	public function load($statusId)
	{
		$data = Rd_Dao_Reserve_Status::get($statusId);
		$this->_id = $data['id'];
		$this->_token = $data['token'];
		$this->_staffLabel = $data['staff_label'];
		$this->_facultyLabel = $data['faculty_label'];
		$this->_description = $data['description'];
		$this->_enabled = $data['enabled'];
		$this->_order = $data['order'];
		return $this;
	}
	
	public function getId()
	{
		return $this->_id;
	}
	
	public function getStaffLabel()
	{
		return $this->_staffLabel;
	}
	
	public function getFacultyLabel()
	{
		return $this->_facultyLabel;
	}
	
	public function getCount()
	{
		if (is_null($this->_count)){
			$this->_count = Rd_Dao_Reserve_Status::getCountForStatus($this->_id);
		}
		return $this->_count;
	}
	
	public function getLabel()
	{
		return 
			Account_Rd::atLeastStaff()
			? $this->getStaffLabel()
			: $this->getFacultyLabel();
	}
	
	public function getDescription()
	{
		return $this->_description;
	}
	
	public function getOrder()
	{
		return $this->_order;
	}
	
	public function isEnabled()
	{
		return $this->_enabled;
	}
	
	public static function create($staffLabelOrArray, $facultyLabel='', $description='', $order = 1)
	{
		if (is_array($staffLabelOrArray)) {
			$staffLabel = Rd_Array::extract('staff_label', $staffLabelOrArray);
			$facultyLabel = Rd_Array::extract('faculty_label', $staffLabelOrArray, $staffLabel);
			$description = Rd_Array::extract('description', $staffLabelOrArray, '');
			$order = Rd_Array::extract('order', $staffLabelOrArray, 1);
		} else {
			$staffLabel = $staffLabelOrArray;
		}
		
		if(is_null($staffLabel) || '' == trim($staffLabel)) {
			throw new Exception('Unable to create reqest status option. Staff Label is required.');
		}
		$id = Rd_Dao_Reserve_Status::create($staffLabel, $facultyLabel, $description, $order);
		if (!$id) {
			throw new Exception('Unable to create request status option. Insert failed.');
		}
		return new Rd_Request_Status($id);
	}
	
	public static function update($idOrArray, $staffLabel=NULL, $facultyLabel = NULL, $description = NULL, $order = NULL, $enabled = NULL)
	{
		if (is_array($idOrArray)) {
			$id = Rd_Array::extractOptional('id', $idOrArray);
			$staffLabel = Rd_Array::extractOptional('staff_label', $idOrArray);
			$facultyLabel = Rd_Array::extractOptional('faculty_label', $idOrArray);
			$description = Rd_Array::extractOptional('description', $idOrArray);
			$order = Rd_Array::extractOptional('order', $idOrArray);
			$enabled = Rd_Array::extractOptional('enabled', $idOrArray);
		} else {
			$id = $idOrArray;
		}
		
		if (is_null($id) || '' == trim($id) || 0 == $id) {
			throw new Exception('Unable to update reqest status option. Id is required.');
		}
		if(!is_null($staffLabel) && '' == trim($staffLabel)) {
			throw new Exception('Unable to update reqest status option. Staff Label is required.');
		}
		$success = Rd_Dao_Reserve_Status::update($id, $staffLabel, $facultyLabel, $description, $order, $enabled);
		return new Rd_Request_Status($id);
	}
	
	public static function audit($reserveId, $statusId)
	{
		if (is_null($reserveId) || '' == trim($reserveId) || 0 == $reserveId) {
			throw new Exception('Unable to audit the status change. Reserve Id is required.');
		}
		if (is_null($statusId) || '' == trim($statusId) || 0 == $statusId) {
			throw new Exception('Unable to audit the status change. Status Id is required.');
		}
		$date = date('Y-m-d H:i:s');
		$userId = Account_Rd::getId();
		return Rd_Dao_Reserve_Status::audit($reserveId, $statusId, $date, $userId);
	}
	
	public static function getDefaultId()
	{
		if (is_null(self::$_initialStatus)) {
			self::$_initialStatus = self::getNewStatusId();
		}
		return self::$_initialStatus;
	}
	
	public static function getAllOptions()
	{
		return array_merge(self::getOptions(), self::getDisabledOptions());
	}
	
	public static function getOptions()
	{ 
		$ids = Rd_Dao_Reserve_Status::lookupEnabled();
		$options = array();
		foreach($ids as $row) {
			$options[] = new Rd_Request_Status($row['id']);
		}
		return $options;
	}
	
	public static function getDisabledOptions()
	{
		$ids = Rd_Dao_Reserve_Status::lookupDisabled();
		$options = array();
		foreach($ids as $row) {
			$options[] = new Rd_Request_Status($row['id']);
		}
		return $options;
	}
	
	public static function getOptionByName($staffLabel) //#TODO probably deprecate, not reliable
	{
		$id = Rd_Dao_Reserve_Status::lookupByName($staffLabel);
		return new Rd_Request_Status($id);
	}
	
	public static function getOptionByToken($token)
	{
		$id = Rd_Dao_Reserve_Status::lookupByToken($token);
		return new Rd_Request_Status($id);
	}
	
	public static function getActiveStatusId()
	{
		if (!is_null(self::$_activeId)) {
			return self::$_activeId;
		}
		self::$_activeId = Rd_Dao_Reserve_Status::lookupByToken('active');
		return self::$_activeId;
	}
	
	public static function getInactiveStatusId()
	{
		if (!is_null(self::$_inactiveId)) {
			return self::$_inactiveId;
		}
		self::$_inactiveId = Rd_Dao_Reserve_Status::lookupByToken('inactive');
		return self::$_inactiveId;
	}
	
	public static function getNewStatusId()
	{
		if (!is_null(self::$_newId)) {
			return self::$_newId;
		}
		self::$_newId = Rd_Dao_Reserve_Status::lookupByToken('new');
		return self::$_newId;
	}
	
	public static function getDeniedStatusId()
	{
		if (!is_null(self::$_deniedId)) {
			return self::$_deniedId;
		}
		self::$_deniedId = Rd_Dao_Reserve_Status::lookupByToken('denied');
		return self::$_deniedId;
	}
	
	public function isReserved()
	{
		return in_array($this->_id, array(
			Rd_Request_Status::getOptionByToken('SEARCH STACKS'), //#TODO make a more configurable way to do this...
			self::getDefaultId(),
			self::getDeniedStatusId(),
			self::getActiveStatusId(),
			self::getInactiveStatusId(),
			self::getNewStatusId()
		));
	}
	
	public function getTimeEstimate($timeSpan = '2 weeks')
	{
		$data = Rd_Dao_Reserve_Status::getTimeEstimateForStatus($this->_id, $timeSpan);
		$return = array('min' => 0, 'max' => 0, 'average' => 0);
		if(count($data) != 0) {
			$return['average'] = $data['days'] + ($data['hours'] >= 12 ? 1 : 0);
			$split = $data['dev_days'] + ($data['dev_hours'] >= 12 ? 1 : 0);
			$return['min'] = max(0, $return['average'] - $split);
			$return['max'] = $return['average'] + $split;
			$return['count'] = (int)$data['count'];
		}
		return $return;
	}
	
	public static function getTimeEstimateForStatus($statusId)
	{
		$data = Rd_Dao_Reserve_Status::getTimeEstimateForStatus($statusId, '2 weeks');
		$return = array('min' => 0, 'max' => 0, 'average' => 0, 'certainty' => 100);
		if (count($data) == 0) {
			$return['certainty'] = 0;
			return $return;
		}
		if ($data['count'] <= 10) {
			$data = Rd_Dao_Reserve_Status::getTimeEstimateForStatus($statusId, '1 year');
			$return['certainty'] = ($data['count'] <= 10 ? 25 : 12);
		}
		$return['average'] = $data['days'] + ($data['hours'] >= 12 ? 1 : 0);
		$split = $data['dev_days'] + ($data['dev_hours'] >= 12 ? 1 : 0);
		$return['min'] = max(0, $return['average'] - $split);
		$return['max'] = $return['average'] + $split;
		return $return;
	}
	
	public static function clearAuditByCourseInstance($courseInstanceId)
	{
		$result = Rd_Dao_Reserve_Status::clearAuditByCourseInstance($courseInstanceId);
		return (bool)$result;
	}
}